#include "util.h"
#include "event_def.h"
#include "accessevent.h"
#include "database.h"
#include "ludb.h"
#include "uv.h"
#include "mqclient.h"
#include "easymqproducer.h"
#include <list>
#include <sstream>

namespace AccessEvent
{
    uv_loop_t* _loop_uv = NULL;         //事件调度loop

    uv_async_t             _uvAsync;    //收到sdk接收事件，异步通知loop
    std::list<SPassEvent*> _elist;      //sdk接收事件列表
    uv_mutex_t             _elist_mutex;

    uv_timer_t             _uvTimerCar; //loop定时发送过车到mq
    std::list<SPassEvent*> _mqlist_car; //准备发送mq过车事件列表
    CEasyMqProducer        _MqCar;
    
    std::list<SPassEvent*> _mqlist_vio; //准备发送mq违法事件列表
    CEasyMqProducer        _MqVio;

    /** event loop thread */
    static void run_loop_thread(void* arg) {
        while (true) {
            uv_run(_loop_uv, UV_RUN_DEFAULT);
            Sleep(200);
        }
        uv_loop_close(_loop_uv);
		delete _loop_uv;
    }

    //将事件送给线程池进行截图或合成[loop thread]
    static void on_async_addevent(uv_async_t* handle) {
        std::list<SPassEvent *> listTmp;
        uv_mutex_lock(&_elist_mutex);
        listTmp.splice(listTmp.begin(), _elist);
        uv_mutex_unlock(&_elist_mutex);

        for(auto &e:listTmp){
            if(e->nVioCode.empty()) {
                Log::debug("pass event recv:%s %s %s", e->strPlate.c_str(), plate_type(e->ePlateType).c_str(), e->strDevID.c_str());
                _mqlist_car.push_back(e);
            } else {
                Log::debug("vio event recv:%s %s %s %s", e->strPlate.c_str(), plate_type(e->ePlateType).c_str(), e->strDevID.c_str(), e->nVioCode.c_str());
                _mqlist_vio.push_back(e);
            }
        }

        //将违法事件解成json提供给mq线程
        if(!_mqlist_vio.empty()) {
            std::list<std::string> tmp;
            for(auto &e:_mqlist_vio) {
                string msg = "{\"root\":\"vioevent\", \"events\":[" + event2json(e) + "]}";
                tmp.push_back(msg);
                delete e;
            }
            _mqlist_vio.clear();
            _MqVio.produce(tmp);
        }
    }

    //定时器执行发送过车事件到mq[loop thread]
    static void on_timer_car(uv_timer_t* handle){
        if(_mqlist_car.size()==0)
            return;

        Log::debug("on_timer_car event size %d", _mqlist_car.size());
        stringstream ss;
        ss << "{\"root\":\"passevent\", \"events\":[";
        bool first = true;
        for(auto &e:_mqlist_car) {
            if(first) {
                first = false;
            } else {
                ss << ",";
            }
            ss << event2json(e);
            delete e;
        }
        ss << "]}";
        _mqlist_car.clear();

        _MqCar.produce(ss.str());
    }

    void Init(bool carpass /*= true*/, bool vio /*= true*/) {
        //MQ初始化
		if(carpass){
            _MqCar.load("CarMq");
		}
		if(vio) {
            _MqVio.load("VioMq");
		}
		Log::debug("init mq");

        //uv事件初始化
		_loop_uv = new uv_loop_t;
		uv_loop_init(_loop_uv);
        uv_async_init(_loop_uv, &_uvAsync, on_async_addevent);
        uv_mutex_init(&_elist_mutex);

		if(carpass) {
			uv_timer_init(_loop_uv, &_uvTimerCar);
			uv_timer_start(&_uvTimerCar, on_timer_car, 5000, 5000);
		}

        uv_thread_t tid;
        uv_thread_create(&tid, run_loop_thread, _loop_uv);
    }

    void AddEvent(SPassEvent *e){
        //放入列表等待截图或者合成
        uv_mutex_lock(&_elist_mutex);
        _elist.push_back(e);
        uv_mutex_unlock(&_elist_mutex);
        uv_async_send(&_uvAsync);
    }

    void Clean(){
    }

}